package com.zhijian.medical.service.impl;

import cn.hutool.core.date.DateUtil;
import com.zhijian.medical.dao.local.FishMapper;
import com.zhijian.medical.entity.po.*;
import com.zhijian.medical.entity.vo.request.ExperimentFishSearchVo;
import com.zhijian.medical.entity.vo.request.ExperimentProcessSampleSearchVo;
import com.zhijian.medical.entity.vo.response.ExperimentFishDeviceVo;
import com.zhijian.medical.enums.*;
import com.zhijian.medical.holder.CurrentUserHolder;
import com.zhijian.medical.service.*;
import com.zhijian.medical.util.AssertUtil;
import com.zhijian.medical.util.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class FishServiceImpl implements FishService {

    @Autowired
    private FishMapper fishMapper;
    @Autowired
    private ExperimentProcessSampleService processSampleService;

    @Autowired
    private FishAnShiJieguoService anJieguoService;

    @Autowired
    private FishSampleOplogService sampleOplogService;

    @Autowired
    private FishHybridOplogService hybridOplogService;

    @Autowired
    private FishAnShiService anService;

    @Autowired
    private FishHybridService hybridService;

    @Autowired
    private FishSampleReadyService sampleReadyService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private ExperimentProcessSampleLogService sampleLogService;

    /**
     * 编号
     */
    private static final String number = "FZ-SOP-013-01-%s-%s";

    @Override
    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    public Long create(ExperimentFish experimentFish) {
        Date now = new Date();
        String today = DateUtil.formatDate(now);
        //今天有几个实验了
        Integer count = this.count(ExperimentFishSearchVo.builder()
                .startDay(today)
                .build());
        String processNumber = String.format(number, DateUtil.format(now, "yyyyMMdd"), String.format("%02d", count + 1));
        experimentFish.setExperimentNum(processNumber);
        experimentFish.setStatus(ExperimentFishStatusEnum.SYCS.getCode().byteValue());
        // 创建实验
        Long experimentFishId = this.insert(experimentFish);
        // 创建样本准备区
        ExperimentFishSampleReady sampleReady = new ExperimentFishSampleReady();
        sampleReady.setFishId(experimentFishId);
        sampleReady.setCzz(experimentFish.getPersonDto().getName());
        sampleReady.setSyrq(today);
        sampleReadyService.insert(sampleReady);
        // 创建杂交室
        ExperimentFishHybrid hybrid = new ExperimentFishHybrid();
        hybrid.setFishId(experimentFishId);
        hybrid.setCzz(experimentFish.getPersonDto().getName());
        hybridService.insert(hybrid);
        // 创建暗室
        ExperimentFishAn experimentFishAn = new ExperimentFishAn();
        experimentFishAn.setFishId(experimentFishId);
        anService.insert(experimentFishAn);


        experimentFish.getSampleIds().forEach(s -> {
            ExperimentProcessSample experimentProcessSample = processSampleService.selectById(s);
            AssertUtil.notNull(experimentProcessSample, "有样本不存在或者已被删除");
            List<String> samplerProjects = Arrays.asList(experimentProcessSample.getProject().split(","));
            samplerProjects.forEach(s1 -> {
                // 创建暗室结果
                ExperimentFishAnJieguo experimentFishAnJieguo = new ExperimentFishAnJieguo();
                experimentFishAnJieguo.setFishId(experimentFishId);
                experimentFishAnJieguo.setBlh(experimentProcessSample.getMoleculePathologyNumber());
                experimentFishAnJieguo.setFzblh(experimentProcessSample.getMoleculePathologyNumber());
                experimentFishAnJieguo.setCgblh(experimentProcessSample.getConventionPathologyNumber());
                experimentFishAnJieguo.setZdys(experimentFish.getPersonDto().getName());
                experimentFishAnJieguo.setXm(s1);
                anJieguoService.insert(experimentFishAnJieguo);
                // 创建样本区操作记录
                ExperimentFishSampleOplog sampleOplog = new ExperimentFishSampleOplog();
                sampleOplog.setFishId(experimentFishId);
                sampleOplog.setFzblh(experimentProcessSample.getMoleculePathologyNumber());
                sampleOplog.setCgblh(experimentProcessSample.getConventionPathologyNumber());
                sampleOplog.setXm(s1);
                sampleOplogService.insert(sampleOplog);
                // 创建杂交室操作记录
                ExperimentFishHybridOplog hybridOplog = new ExperimentFishHybridOplog();
                hybridOplog.setFishId(experimentFishId);
                hybridOplog.setBlh(experimentProcessSample.getMoleculePathologyNumber());
                hybridOplog.setFzblh(experimentProcessSample.getMoleculePathologyNumber());
                hybridOplog.setCgblh(experimentProcessSample.getConventionPathologyNumber());
                hybridOplog.setXm(s1);
                if (s1.equals(ExperimentTypeEnum.FISH.getProject().get(0))) {
                    //如果项目是HER2的话，程序直接为2
                    hybridOplog.setCx(FishHybridProcedureEnum.TWO.getDesc());
                }
                hybridOplogService.insert(hybridOplog);

            });
            processSampleService.updateByPrimaryKeySelective(ExperimentProcessSample.builder().id(s).experimentProcessId(experimentFishId)
                    //状态改为检测中
                    .status(ExperimentFishSampleStatusEnum.JCZ.getCode().byteValue()).build());
            sampleLogService.create(ExperimentProcessSampleLog.builder()
                    .sampleId(s)
                    .mainType(ExperimentTypeEnum.FISH.getCode().byteValue())
                    .op(String.format("%s%s-%s", experimentFish.getName(), experimentFish.getExperimentNum(), ExperimentFishSampleStatusEnum.NEW.getType()))
                    .opUser(CurrentUserHolder.getUser().getName())
                    .fishId(experimentFishId)
                    .build()
            );
        });


        return experimentFishId;

    }

    public Long insert(ExperimentFish experimentFish) {

        return fishMapper.insert(experimentFish) > 0 ? experimentFish.getId() : 0L;
    }

    @Override
    public ExperimentFish detail(Long id) {
        ExperimentFish experimentFish = selectByPrimaryKey(id);
        if (Objects.nonNull(experimentFish)) {
            experimentFish.setExperimentProcessSampleList(processSampleService.selectList(ExperimentProcessSampleSearchVo.builder().experimentProcessId(id).mainType(ExperimentTypeEnum.FISH.getCode().byteValue()).build()));
        }
        return experimentFish;
    }

    @Override
    public ExperimentFish selectByPrimaryKey(Long id) {
        return fishMapper.selectByPrimaryKey(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    public Boolean update(ExperimentFish experimentFish) {
        Boolean b = this.updateByPrimaryKeySelective(experimentFish);
        if (b) {
            //先把之前的关联样本关系删掉
            processSampleService.removeRelation(experimentFish.getId(), ExperimentTypeEnum.FISH.getCode().byteValue());
            experimentFish.getSampleIds().forEach(s -> processSampleService.updateByPrimaryKeySelective(ExperimentProcessSample.builder().id(s).experimentProcessId(experimentFish.getId())
                    //状态改为检测中
                    .status(ExperimentProcessSampleStatusEnum.ING.getCode().byteValue()).build()));

        }
        return b;
    }

    @Override
    public Boolean updateByPrimaryKeySelective(ExperimentFish experimentFish) {
        return fishMapper.updateByPrimaryKeySelective(experimentFish) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    public Boolean delete(Long id) {
        ExperimentFish experimentFish = ExperimentFish.builder().id(id).deleted((byte) 1).sampleIds(new ArrayList<>()).build();
        return this.update(experimentFish);
    }

    @Override
    public Page<ExperimentFish> selectPage(ExperimentFishSearchVo experimentFishSearchVo) {
        //先直接查总数
        int count = count(experimentFishSearchVo);
        //分页
        Page<ExperimentFish> page = new Page<>(true, count, experimentFishSearchVo.getPageNum(), experimentFishSearchVo.getPageSize());
        experimentFishSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<ExperimentFish> list = this.selectList(experimentFishSearchVo);
        page.setData(list);
        return page;
    }

    public Integer count(ExperimentFishSearchVo experimentFishSearchVo) {
        return fishMapper.count(experimentFishSearchVo);
    }

    public List<ExperimentFish> selectList(ExperimentFishSearchVo experimentFishSearchVo) {
        return fishMapper.selectList(experimentFishSearchVo);
    }

    @Override
    public ExperimentFishDeviceVo devices() {
        ExperimentFishDeviceVo experimentFishDeviceVo = new ExperimentFishDeviceVo();
        experimentFishDeviceVo.setBylxj(deviceService.selectListByType(FishDeviceTypeEnum.BYLXJ.getName()));
        experimentFishDeviceVo.setDwsyg(deviceService.selectListByType(FishDeviceTypeEnum.DWSYG.getName()));
        experimentFishDeviceVo.setHx(deviceService.selectListByType(FishDeviceTypeEnum.HX.getName()));
        experimentFishDeviceVo.setSwsyg(deviceService.selectListByType(FishDeviceTypeEnum.SWSYG.getName()));
        experimentFishDeviceVo.setThermolxj(deviceService.selectListByType(FishDeviceTypeEnum.THERMOLXJ.getName()));
        experimentFishDeviceVo.setYgxwj(deviceService.selectListByType(FishDeviceTypeEnum.YGXWJ.getName()));
        experimentFishDeviceVo.setZjy(deviceService.selectListByType(FishDeviceTypeEnum.ZJY.getName()));
        return experimentFishDeviceVo;
    }

}
